package com.lm.httpclient.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.Map;

@Component
public class HttpClientUtil {
    private final static Logger logger= LoggerFactory.getLogger(HttpClientUtil.class);

    private static CloseableHttpClient httpClient = null;

    private static final Charset CHAR_SET = Charset.forName("utf-8");

    private static PoolingHttpClientConnectionManager cm;
    public  HttpClientUtil(){
        init();
    }

    public      void init() {
        cm = new PoolingHttpClientConnectionManager();
        //设置最大连接数
        cm.setMaxTotal(300);
        //设置每个主机地址的并发数
//        cm.setDefaultMaxPerRoute(100);
        cm.setDefaultConnectionConfig(ConnectionConfig.custom()
                .setCharset(CHAR_SET).build());
        SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(30000)
                .setSoReuseAddress(true).build();
        cm.setDefaultSocketConfig(socketConfig);
        httpClient = HttpClientBuilder.create().setConnectionManager(cm)
                .build();
    }



    // 创建一个 CloseableHttpClient，并绕过 SSL 验证
    private static  org.apache.http.impl.client.CloseableHttpClient createHttpClient() {
        // 配置忽略证书验证
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(30000)  // 设置连接超时
                .setSocketTimeout(30000)   // 设置读取超时
                .build();

        return HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setSSLContext(createSSLContext())  // 使用自定义的 SSLContext，绕过证书验证
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)  // 忽略主机名验证
                .build();
    }

    // 创建绕过证书验证的 SSLContext
    private static SSLContext createSSLContext() {
        try {
            // 初始化一个忽略证书验证的 SSLContext
            TrustManager[] trustAllCertificates = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        }
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        }
                    }
            };

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCertificates, new java.security.SecureRandom());
            return sc;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public  CloseableHttpClient getHttpClient() {

        int timeout=5;
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(timeout * 1000) //设置连接超时时间，单位毫秒
                .setSocketTimeout(timeout * 1000).build(); //请求获取数据的超时时间，单位毫秒
        CloseableHttpClient _httpClient = HttpClients.custom()
                .setConnectionManager(cm)
//                .setDefaultRequestConfig(config) //使用此方法连接池会关闭
                .setConnectionManagerShared(true)
                .build();
        if(cm!=null&&cm.getTotalStats()!=null) { //打印连接池的状态
            logger.info("now client pool {}"+cm.getTotalStats().toString());
        }
        return _httpClient;
    }


    /**
     * get请求
     *
     * @return
     */
    public   String doGet(String url) {
        try {
            HttpClient client = getHttpClient();
            //发送get请求
            HttpGet request = new HttpGet(url);
            HttpResponse response = client.execute(request);

            /**请求发送成功，并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                String strResult = EntityUtils.toString(response.getEntity());
                request.releaseConnection();
                return strResult;
            }
        } catch (IOException e) {
            logger.error("doGet error:{}",e);
        }

        return null;
    }

    /**
     * post请求 参数为map格式
     *
     * @param url
     * @param params
     * @return
     */
    public  String doPost(String url, Map params) {

        BufferedReader in = null;
        try {
            // 定义HttpClient
            CloseableHttpClient client =getHttpClient();

            // 实例化HTTP方法
            HttpPost request = new HttpPost();
            request.setURI(new URI(url));
            request.setHeader("Content-Type","application/json; charset=utf-8");
            StringEntity s = new StringEntity(JSON.toJSONString(params));
            request.setEntity(s);
            HttpResponse response = client.execute(request);
            int code = response.getStatusLine().getStatusCode();
            if (code == 200) {
                //返回json格式
                String res = EntityUtils.toString(response.getEntity());
                request.releaseConnection();
                return res;
            } else {    //
                System.out.println("状态码：" + code);
                return null;
            }
        } catch (Exception e) {
            logger.error("doPost error:{}",e);
            return null;
        }
    }

    // 将输入流读取到字节数组中
    private static byte[] readStreamToByteArray(InputStream inputStream) throws IOException {
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            return byteArrayOutputStream.toByteArray();
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 以post方式  请求参数为json格式
     * @param url
     * @param json
     * @return
     */
    public  String doPost(String url, JSONObject json){
        HttpPost post = new HttpPost(url);
        try {
            if (httpClient == null){
                // httpClient = HttpClientBuilder.create().build();
                httpClient= HttpClients.custom().setConnectionManager(cm).setConnectionManagerShared(true).build();
            }
            httpClient=getHttpClient();
            //api_gateway_auth_token自定义header头，用于token验证使用
            //  post.addHeader("api_gateway_auth_token", tokenString);
            post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
            post.setHeader("Content-type", "application/json;charset=utf-8");
            post.setHeader("Connection", "Close");
            StringEntity s = new StringEntity(json.toString());
            s.setContentEncoding("UTF-8");
            //发送json数据需要设置contentType
            s.setContentType("application/x-www-form-urlencoded");
            //设置请求参数
            post.setEntity(s);
            HttpResponse response = httpClient.execute(post);

            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                //返回json格式
                String res = EntityUtils.toString(response.getEntity());
                post.releaseConnection();
                return res;
            }
        } catch (Exception e) {
            logger.error("excep:"+e.getMessage());
        }finally {
            if (post != null)
                post.releaseConnection();
            if (httpClient != null){
                try {
                    httpClient.close();
                } catch (IOException e) {
                }
            }

        }
        return null;
    }

    public static void main(String[] args) {
        //URL
        String URL = "https://gljcpt.yciccloud.com:9507/glaf/website/public/form/file?method=downloadById&id=6e0336c88f6f4feabc8b6883910b7c9b&to=acthis&acthisid=6e0336c88f6f4feabc8b6883910b7c9b";
        // 目标字段是 result，直接传递文件内容
        byte[] fileContent = null;

        try  {
            // 创建一个关闭式 HttpClient
            org.apache.http.impl.client.CloseableHttpClient client = createHttpClient();
            // 创建 GET 请求
            HttpGet httpGet = new HttpGet(URL);

            // 发送请求并接收文件内容
            CloseableHttpResponse response = client.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode == HttpStatus.SC_OK){
                logger.info("");
            }
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                // 读取响应体内容到 byte[]
                InputStream inputStream = entity.getContent();
                fileContent = readStreamToByteArray(inputStream);

                // 释放资源
                EntityUtils.consume(entity);
            }

            // 将文件内容作为 result 字段传递给下一个节点
            //setOutputRowData(0, fileContent);  // 假设 'result' 字段在输出中索引为 0

            // 记录日志
            //logBasic("文件下载成功，内容已存储到 result 字段");

        } catch (IOException e) {
            // 处理异常
            //logError("下载文件时出现错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
